package com.lxk.mall.pms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lxk.mall.pms.controller.app.vo.ProductCategoryListReqVO;
import com.lxk.mall.pms.domain.PmsProductCategory;
import com.lxk.mall.pms.domain.bo.category.PmsProductCategoryBo;
import com.lxk.mall.pms.domain.vo.category.PmsProductCategoryVo;
import com.lxk.mall.pms.enums.PmsErrorCodeConstants;
import com.lxk.mall.pms.enums.ProductConstants;
import com.lxk.mall.pms.mapper.PmsProductCategoryMapper;
import com.lxk.mall.pms.service.IPmsProductCategoryService;
import com.lxk.mall.pms.service.IPmsProductSpuService;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.enums.CommonStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 商品分类Service业务层处理
 *
 * @author Lion Li
 * @date 2024-06-06
 */
@RequiredArgsConstructor
@Service
public class PmsProductCategoryServiceImpl implements IPmsProductCategoryService {

    private final PmsProductCategoryMapper baseMapper;

    @Autowired
    @Lazy
    private IPmsProductSpuService spuService;
    /**
     * 查询IdList商品分类Map
     */
    @Override
    public Map<Long, PmsProductCategoryVo> queryMapByIdList(List<Long> idList) {
        return this.queryByIdList(idList).stream().collect(Collectors.toMap(PmsProductCategoryVo::getId, v -> v));
    }


    @Override
    public Map<Long, PmsProductCategoryVo> queryMap(PmsProductCategoryBo bo) {
        return  this.queryList(bo).stream().collect(Collectors.toMap(PmsProductCategoryVo::getId, v -> v));
    }

    /**
     * 查询商品分类IdList
     */
    @Override
    public List<PmsProductCategoryVo> queryByIdList(List<Long> idList) {
        if (CollUtil.isEmpty(idList)) {
            return CollUtil.newArrayList();
        }
        LambdaQueryWrapper<PmsProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.in(PmsProductCategory::getId, idList);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 查询商品分类
     *
     * @param id 主键
     * @return 商品分类
     */
    @Override
    public PmsProductCategoryVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询商品分类列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 商品分类分页列表
     */
    @Override
    public TableDataInfo<PmsProductCategoryVo> queryPageList(PmsProductCategoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PmsProductCategory> lqw = buildQueryWrapper(bo);
        Page<PmsProductCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的商品分类列表
     *
     * @param bo 查询条件
     * @return 商品分类列表
     */
    @Override
    public List<PmsProductCategoryVo> queryList(PmsProductCategoryBo bo) {
        LambdaQueryWrapper<PmsProductCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PmsProductCategory> buildQueryWrapper(PmsProductCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PmsProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getParentId() != null, PmsProductCategory::getParentId, bo.getParentId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), PmsProductCategory::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getPicUrl()), PmsProductCategory::getPicUrl, bo.getPicUrl());
        lqw.eq(bo.getSort() != null, PmsProductCategory::getSort, bo.getSort());
        lqw.eq(bo.getStatus() != null, PmsProductCategory::getStatus, bo.getStatus());
        lqw.orderByAsc(PmsProductCategory::getSort);
        return lqw;
    }

    /**
     * 新增商品分类
     *
     * @param bo 商品分类
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(PmsProductCategoryBo bo) {
        PmsProductCategory add = MapstructUtils.convert(bo, PmsProductCategory.class);
        validateParentProductCategory(add.getParentId());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改商品分类
     *
     * @param bo 商品分类
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(PmsProductCategoryBo bo) {
        PmsProductCategory update = MapstructUtils.convert(bo, PmsProductCategory.class);
        // 校验分类是否存在
        validateProductCategoryExists(update.getId());
        // 校验父分类存在
        validateParentProductCategory(update.getParentId());
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 验证产品分类是否存在
     *
     * @param id 分类ID
     * @throws ServiceException 如果分类不存在，则抛出服务异常
     */
    private void validateProductCategoryExists(Long id) {
        // 根据ID查询分类信息
        PmsProductCategory category = baseMapper.selectById(id);
        // 如果查询结果为空，表示该分类不存在
        if (category == null) {
            throw new ServiceException(PmsErrorCodeConstants.CATEGORY_NOT_EXISTS);
        }
    }



    /**
     * 校验并批量删除商品分类信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            for (Long id : ids) {
                // 校验分类是否存在
                validateProductCategoryExists(id);
                // 校验是否还有子分类
                if (baseMapper.selectCountByParentId(id) > 0) {
                    throw new ServiceException(PmsErrorCodeConstants.CATEGORY_EXISTS_CHILDREN);
                }
                // 校验分类是否绑定了 SPU
                Long spuCount = spuService.getSpuCountByCategoryId(id);
                if (spuCount > 0) {
                    throw new ServiceException(PmsErrorCodeConstants.CATEGORY_HAVE_BIND_SPU);
                }
            }

        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<PmsProductCategory> getEnableCategoryList() {
        return baseMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
    }

    @Override
    public List<PmsProductCategory> getEnableCategoryList(List<Long> ids) {
        return baseMapper.selectListByIdAndStatus(ids, CommonStatusEnum.ENABLE.getStatus());
    }

    @Override
    public List<PmsProductCategory> getCategoryList(ProductCategoryListReqVO listReqVO) {
        return baseMapper.selectList(listReqVO);
    }

    @Override
    public void validateCategory(Long categoryId) {
        PmsProductCategory category = baseMapper.selectById(categoryId);
        if (category == null) {
            throw new ServiceException(PmsErrorCodeConstants.CATEGORY_NOT_EXISTS);
        }
        if (Objects.equals(category.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
            throw new ServiceException(PmsErrorCodeConstants.CATEGORY_DISABLED, category.getName());
        }
    }

    @Override
    public Integer getCategoryLevel(Long categoryId) {
        if (Objects.equals(categoryId,ProductConstants.PARENT_ID_NULL)) {
            return 0;
        }
        int level = 1;
        // for 的原因，是因为避免脏数据，导致可能的死循环。一般不会超过 100 层哈
        for (int i = 0; i < Byte.MAX_VALUE; i++) {
            // 如果没有父节点，break 结束
            PmsProductCategory category = baseMapper.selectById(categoryId);
            if (category == null
                || Objects.equals(category.getParentId(), ProductConstants.PARENT_ID_NULL)) {
                break;
            }
            // 继续递归父节点
            level++;
            categoryId = category.getParentId();
        }
        return level;
    }

    /**
     * 验证父级商品分类的合法性。
     * <p>
     * 此方法用于在创建或更新商品分类时，验证指定的父分类ID是否有效。
     * 它主要检查以下几点：
     * 1. 父分类ID是否为根分类的特殊标识，如果是，则认为验证通过。
     * 2. 父分类ID对应的分类是否存在数据库中，如果不存在，则抛出异常。
     * 3. 父分类是否为一级分类，即其父分类ID是否为根分类的特殊标识，如果不是，则抛出异常。
     * </p>
     *
     * @param id 待验证的父级商品分类的ID。
     * @throws ServiceException 如果父分类不存在或不是一级分类，则抛出此异常。
     */
    private void validateParentProductCategory(Long id) {
        // 如果是根分类，无需验证
        if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) {
            return;
        }
        // 父分类不存在
        PmsProductCategory category = baseMapper.selectById(id);
        if (category == null) {
            throw new ServiceException(PmsErrorCodeConstants.CATEGORY_PARENT_NOT_EXISTS);
        }
        // 父分类不能是二级分类
        if (!Objects.equals(category.getParentId(), ProductConstants.PARENT_ID_NULL)) {
            throw new ServiceException(PmsErrorCodeConstants.CATEGORY_PARENT_NOT_FIRST_LEVEL);
        }
    }

}
